package com.zhaoyd.shardingdemo;

import com.zaxxer.hikari.HikariDataSource;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.MapListHandler;
import org.apache.shardingsphere.driver.api.ShardingSphereDataSourceFactory;
import org.apache.shardingsphere.infra.config.algorithm.ShardingSphereAlgorithmConfiguration;
import org.apache.shardingsphere.sharding.algorithm.sharding.classbased.ClassBasedShardingAlgorithm;
import org.apache.shardingsphere.sharding.algorithm.sharding.datetime.AutoIntervalShardingAlgorithm;
import org.apache.shardingsphere.sharding.api.config.ShardingRuleConfiguration;
import org.apache.shardingsphere.sharding.api.config.rule.ShardingTableRuleConfiguration;
import org.apache.shardingsphere.sharding.api.config.strategy.sharding.ComplexShardingStrategyConfiguration;
import org.apache.shardingsphere.sharding.api.config.strategy.sharding.StandardShardingStrategyConfiguration;
import org.apache.shardingsphere.transaction.config.TransactionRuleConfiguration;
import org.apache.shardingsphere.transaction.core.TransactionType;
import org.apache.shardingsphere.transaction.core.TransactionTypeHolder;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.*;

public class ShardingMain {
    public static void main(String[] args) throws SQLException {
        String schemaName = "user"; // 指定逻辑 Schema 名称
//        ModeConfiguration modeConfig = ... // 构建运行模式
        // 配置表规则

//        Properties props = ... // 构建属性配置
        Map<String, DataSource> dataSourceMap = new HashMap<>();

// 配置第 1 个数据源
        HikariDataSource dataSource1 = new HikariDataSource();
        dataSource1.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource1.setJdbcUrl("jdbc:mysql://10.8.4.212:3306/userdb?serverTimezone=GMT%2B8");
        dataSource1.setUsername("root");
        dataSource1.setPassword("root123456");
        dataSourceMap.put("m1", dataSource1);

// 配置第 2 个数据源
        HikariDataSource dataSource2 = new HikariDataSource();
        dataSource2.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource2.setJdbcUrl("jdbc:mysql://10.8.4.212:3306/userdb2?serverTimezone=GMT%2B8");
        dataSource2.setUsername("root");
        dataSource2.setPassword("root123456");
        dataSourceMap.put("m2", dataSource2);




        Properties p = new Properties();
        p.setProperty("sql-show","true");
        DataSource dataSource = ShardingSphereDataSourceFactory.createDataSource(schemaName, null, dataSourceMap, Arrays.asList(userShardingRuleConfiguration(),schoolShardingRuleConfiguration(),new TransactionRuleConfiguration(TransactionType.BASE.name(),null)), p);


        TransactionTypeHolder.set(TransactionType.BASE);
        Connection connection = dataSource.getConnection();
        connection.setAutoCommit(false);
        QueryRunner queryRunner=new QueryRunner();
        List<Map<String, Object>> query = queryRunner.query(connection,"select * from user u join school s on ( u.id = 1 and u.age=1 and u.cid=s.id ) ", new MapListHandler());
//
        queryRunner.update(connection,"delete from user");
        queryRunner.update(connection,"delete from school");

        for(int i=1;i<=1;++i){
            queryRunner.update(connection,"insert into user(id,name,age,cid) values(?,?,?,?)",i,"n"+i,i,i);
            queryRunner.update(connection,"insert into school(id,school_name) values(?,?)",i,"s"+i);
        }
        connection.commit();
//        System.out.print(query);

    }

    static ShardingRuleConfiguration userShardingRuleConfiguration(){
        // Configure order table rule
        ShardingTableRuleConfiguration orderTableRuleConfig = new ShardingTableRuleConfiguration("user", "m$->{1..2}.user_$->{1..2}");

// Configure database sharding strategy
        orderTableRuleConfig.setDatabaseShardingStrategy(new StandardShardingStrategyConfiguration("id", "dbShardingAlgorithm"));

// Configure table sharding strategy
        orderTableRuleConfig.setTableShardingStrategy(new StandardShardingStrategyConfiguration("id", "tableShardingAlgorithm"));

// Omit t_order_item table rule configuration ...
// ...

// Configure sharding rule
        ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration();
        shardingRuleConfig.getTables().add(orderTableRuleConfig);

// Configure database sharding algorithm
        Properties dbShardingAlgorithmrProps = new Properties();
        dbShardingAlgorithmrProps.setProperty("algorithm-expression", "m${(id+1) % 2+1}");
        shardingRuleConfig.getShardingAlgorithms().put("dbShardingAlgorithm", new ShardingSphereAlgorithmConfiguration("INLINE", dbShardingAlgorithmrProps));

// Configure table sharding algorithm
        Properties tableShardingAlgorithmrProps = new Properties();
//        tableShardingAlgorithmrProps.setProperty("algorithm-expression", "user_${id % 2}");
//        shardingRuleConfig.getShardingAlgorithms().put("tableShardingAlgorithm", new ShardingSphereAlgorithmConfiguration("INLINE", tableShardingAlgorithmrProps));
        tableShardingAlgorithmrProps.setProperty("strategy", "STANDARD");
        tableShardingAlgorithmrProps.setProperty("algorithmClassName", "wei.TableShardingAlg");
        /**
         * @see ClassBasedShardingAlgorithm#getType()
         * @see ClassBasedShardingAlgorithm#init()
         */
        shardingRuleConfig.getShardingAlgorithms().put("tableShardingAlgorithm", new ShardingSphereAlgorithmConfiguration("CLASS_BASED", tableShardingAlgorithmrProps));

        return shardingRuleConfig;
    }

    static ShardingRuleConfiguration schoolShardingRuleConfiguration(){
        // Configure order table rule
        ShardingTableRuleConfiguration orderTableRuleConfig = new ShardingTableRuleConfiguration("school", "m$->{1..2}.school");

// Configure database sharding strategy
        orderTableRuleConfig.setDatabaseShardingStrategy(new StandardShardingStrategyConfiguration("id", "dbShardingAlgorithm"));

// Configure table sharding strategy
        orderTableRuleConfig.setTableShardingStrategy(new StandardShardingStrategyConfiguration("id", "tableShardingAlgorithm"));

// Omit t_order_item table rule configuration ...
// ...

// Configure sharding rule
        ShardingRuleConfiguration shardingRuleConfig = new ShardingRuleConfiguration();
        shardingRuleConfig.getTables().add(orderTableRuleConfig);

// Configure database sharding algorithm
        Properties dbShardingAlgorithmrProps = new Properties();
        dbShardingAlgorithmrProps.setProperty("algorithm-expression", "m${(id+1) % 2+1}");
        shardingRuleConfig.getShardingAlgorithms().put("dbShardingAlgorithm", new ShardingSphereAlgorithmConfiguration("INLINE", dbShardingAlgorithmrProps));

// Configure table sharding algorithm
        Properties tableShardingAlgorithmrProps = new Properties();
//        tableShardingAlgorithmrProps.setProperty("algorithm-expression", "user_${id % 2}");
//        shardingRuleConfig.getShardingAlgorithms().put("tableShardingAlgorithm", new ShardingSphereAlgorithmConfiguration("INLINE", tableShardingAlgorithmrProps));
        tableShardingAlgorithmrProps.setProperty("strategy", "STANDARD");
        tableShardingAlgorithmrProps.setProperty("algorithmClassName", "wei.TableShardingAlg");
        /**
         * @see ClassBasedShardingAlgorithm#getType()
         * @see ClassBasedShardingAlgorithm#init()
         */
//        shardingRuleConfig.getShardingAlgorithms().put("tableShardingAlgorithm", new ShardingSphereAlgorithmConfiguration("CLASS_BASED", tableShardingAlgorithmrProps));
        return shardingRuleConfig;
    }
}
